package org.example.gradleDemo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

@SuppressWarnings("ALL")
public final class TcpServerDemo {
    public void StartTcpServer()
    {
        try
        {
           final Charset utf8 = StandardCharsets.UTF_8;

            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            InetSocketAddress endpoint = new InetSocketAddress(9527);
            serverSocketChannel.socket().bind(endpoint);
            serverSocketChannel.configureBlocking(false);  //  not blocking

            // open selector
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            final  int timeout = 0;
            while(true)
            {
                System.out.println("begin wait select  :" );
                selector.select(timeout);
                var iterator = selector.selectedKeys().iterator();
                System.out.println("wait client :" );

                var byteBuffer = ByteBuffer.allocate(1024);
                var writeBuffer = ByteBuffer.allocate(128);

                while(iterator.hasNext())
                {
                    var key = iterator.next();
                    if(key.isAcceptable())
                    {
                        //处理链接事件
                        var socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);  //设置为非阻塞
                        System.out.println("client:" + socketChannel.getLocalAddress() + " is connect");
                        socketChannel.register(selector, SelectionKey.OP_READ); //注册客户端读取事件到selector

                    }
                    else if(key.isReadable())
                    {
                        // 处理可读事件
                        var channel = (SocketChannel) key.channel();
                        byteBuffer.clear();
                        channel.read(byteBuffer);
                        byteBuffer.flip();
                        var content = utf8.decode(byteBuffer).toString();
                        System.out.println("client:" + channel.getLocalAddress() + " send " + content);
                        key.interestOps(SelectionKey.OP_WRITE);
                    }
                    else if(key.isWritable())
                    {
                        // 处理可读事件
                        writeBuffer.rewind();
                        writeBuffer.put("server write".getBytes(StandardCharsets.UTF_8));
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        socketChannel.write(writeBuffer);
                        key.interestOps(SelectionKey.OP_READ);
                    }
                    else {
                        System.out.println("wait client :" );
                    }
                    // 移除已处理事件
                    iterator.remove();
                    Thread.sleep(1000);
                }

            }

        }
        catch (IOException | InterruptedException io)
        {
            System.out.println(String.format("error:%s",io.getMessage()));
        }


    }
}
